/**
 * 
 */
package org.hotpotmaterial.codegenn2.config.security.filter;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.hotpotmaterial.codegenn2.common.HmCodeGenConstants;
import org.hotpotmaterial.codegenn2.common.HmLogConstants;
import org.hotpotmaterial.codegenn2.config.bean.LogConfig;
import org.hotpotmaterial.codegenn2.config.bean.LoginPrincipal;
import org.hotpotmaterial.codegenn2.dto.LoginDTO;
import org.hotpotmaterial.codegenn2.entity.HmteamAccount;
import org.hotpotmaterial.codegenn2.utils.RandomUtil;
import org.hotpotmaterial.codegenn2.utils.RequestUtil;
import org.slf4j.Logger;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;

/**
 * @author cakydeveloper
 *
 */
@Slf4j
public class LoginFilter extends UsernamePasswordAuthenticationFilter {

	private static Logger accessLogger = LogConfig.getLogger(HmLogConstants.ACCESS_LOGNAME);

	private static Logger resultLogger = LogConfig.getLogger(HmLogConstants.RESULT_LOGNAME);

	private AuthenticationManager authenticationManager;

	public LoginFilter(AuthenticationManager authenticationManager) {
		this.authenticationManager = authenticationManager;
	}

	/**
	 * 接收并解析用户凭证
	 */
	@Override
	public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
			throws AuthenticationException {
		String tag = RandomUtil.getRandom(16, RandomUtil.TYPE.LETTER_CAPITAL_NUMBER);
		String username = (String) req.getParameter("username");
		String password = (String) req.getParameter("password");
		Integer usertype = Integer.valueOf((String) req.getParameter("usertype"));
		// 日志
		accessLogger.info(RequestUtil.getRequestInfo(tag, "/login", "username=" + username + ",password=" + password));
		return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
				LoginPrincipal.builder().type(usertype).username(username).traceId(tag).build(), password,
				new ArrayList<>()));
	}

	/**
	 * 用户成功登录后，这个方法会被调用，我们在这个方法里生成token
	 */
	@Override
	protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
			Authentication auth) throws IOException, ServletException {
		// 从Authentication中获取用户
		HmteamAccount currentUser = (HmteamAccount) auth.getPrincipal();
		// 设值ContentType
		res.setContentType("application/json;charset=UTF-8");
		// 初始化RESPONSE BODY的对象
		LoginDTO result = new LoginDTO();
		if (currentUser.getIsDeleted() == HmCodeGenConstants.DATA_IS_TEMP_VALID) {
			result.setSuccess(true);
			// 返回状态403
			result.setStatus(HttpServletResponse.SC_FORBIDDEN);
			result.setErrorMessage("User is not valid temporarily");
			// 设置错误消息
			result.setData(currentUser.getAuthToken());
		} else {
			result.setSuccess(true);
			// 设置HTTP CODE
			result.setStatus(res.getStatus());
			// 将当前用户放入RESPONSE中
			result.setData(currentUser);
		}
		// 日志
		StringBuilder sb = new StringBuilder();
		sb.append("execution_time: [0ms], return_value: [").append(result.toString()).append("]").append(" >>>> ")
				.append(currentUser.getTraceId());
		resultLogger.info(sb.toString());
		// 用PrintWriter写入RESPONSE
		PrintWriter out = null;
		// 转JSON
		ObjectMapper mapper = new ObjectMapper();
		// 将LoginResponseDTO转为JSON字符串
		String resultJson = mapper.writeValueAsString(result);
		try {
			// 获取PrintWriter
			out = res.getWriter();
			// 写入
			out.append(resultJson);
		} catch (IOException e) {
			log.error("", e);
		} finally {
			if (out != null) {
				// 关闭PrintWriter
				out.close();
			}
		}
	}

	@Override
	protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException failed) throws IOException, ServletException {
		SecurityContextHolder.clearContext();

		// 设置ContentType
		response.setContentType("application/json;charset=UTF-8");
		// 设置HTTP协议CODE
		response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
		// 初始化RESPONSE消息体的对象
		LoginDTO result = new LoginDTO();
		// 设置HTTP协议CODE
		response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
		result.setSuccess(true);
		// 返回状态403
		result.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
		// 设置错误消息
		result.setErrorMessage(failed.getMessage());
		// 日志
		StringBuilder sb = new StringBuilder();
		sb.append("return_value: ").append(failed.getMessage());
		resultLogger.info(sb.toString());
		// 写入RESPONSE
		PrintWriter out = null;
		// 转JSON
		ObjectMapper mapper = new ObjectMapper();
		// 将RESULT对象转为JSON字符串
		String resultJson = mapper.writeValueAsString(result);
		try {
			// 写入RESPONSE
			out = response.getWriter();
			out.append(resultJson);
		} catch (IOException e) {
			log.error("", e);
		} finally {
			if (out != null) {
				// 关闭WRITER
				out.close();
			}
		}
	}

}
